﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Interfaces.CommonData;
using StockInfoDataLayer;
using StockInfoFacade.Adapters;
using StockInfoFacade.Utils;
using StockInfoLoader;

namespace StockInfoFacade
{
    public class StockInfoVM
    {
        private DBManager _mgr;


        public DBStatus DBStatus { get { return _mgr.EvaluateDBStatus(); } }
        // Initiate connectivity
        public StockInfoVM(string connectionString, string dbName)
        {
            _mgr = DBManager.CreateInstance(connectionString, dbName);
            NumberOfThreads = 5;
        }

        // TODO: should react on events
        public DateInterval FromTo { get; set; }

        public int NumberOfThreads { get; set; }


        public DateInterval RetrieveMaxInterval()
        {
            PriceTable ptbl = new PriceTable();
            return ptbl.RetrieveMaxDateInterval();
        }

        // Repopulate database
        public void RefreshDatabase(IndexName idx)
        {
            RefreshDatabase(idx, null);
        }

        public void RefreshDatabase(IndexName idx, BackgroundWorker bw)
        {
            //1. Refresh the tickers
            IndexCompositionLoader iLoader = new IndexCompositionLoader();
            var lstStocks = iLoader.LoadIndexComposition(IndexName.SAndP100);
            StockTable st = new StockTable();
            st.PopulateIndexStocks(lstStocks);
            //2. Refresh the prices no threads
            int allStocksToLoad = lstStocks.Count;
            int currentlyLoadedStocks = 0;

            var pt = new PriceTable();
            pt.ClearTable();

            //2. Refresh the prices
            using (var priceProcessingQueue = new PCQueue(NumberOfThreads))
            {
                var InternalBWM = new StockInfoLoaderThreadAdapter.BW_Metrics(
                                currentlyLoadedStocks
                                , allStocksToLoad
                                , bw);
                lstStocks.ForEach(stock =>
                {
                    var adapter =
                        new Adapters.StockInfoLoaderThreadAdapter(
                            stock.Ticker
                            , stock.Id
                            , FromTo
                            , pt
                            , InternalBWM);

                    priceProcessingQueue.EnqueueItem(adapter.DoLoad);
                });
                priceProcessingQueue.WaitTillEmptyQueue(); // not actually needed, destructor will wait
            }
        }

        public void CreateNewDatabase()
        {
            _mgr.CreateDataBase();
        }

        public void DropDatabase()
        {
            _mgr.DropDataBase();
        }

        public Dictionary<Stock, Dictionary<Stock, Decimal>> GenerateCorrelationMatrix()
        {
            return GenerateCorrelationMatrix(null);
        }

        public Dictionary<Stock, Dictionary<Stock, Decimal>> GenerateCorrelationMatrix(BackgroundWorker bw)
        {
            StockTable stbl = new StockTable();

            List<Stock> lstStocks = stbl.GetIndexStocks();

            PriceTable ptbl = new PriceTable();
            List<StockPrice> lstPrices = ptbl.GetAllPrices();

            StockInfoFacade.BusinessLogic.Correlation C = new StockInfoFacade.BusinessLogic.Correlation();
            Dictionary<Stock, Dictionary<Stock, Decimal>>
                dCorr = C.ComputeMatrix(lstPrices, lstStocks, bw);

            return dCorr;
        }
        
    }
}
